#pragma once
#include <boost/filesystem.hpp>
#include <boost/thread.hpp>
#include <boost/foreach.hpp>
#include <boost/date_time.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include "../include/framefunc.h"
#include <string>
#include <vector>
#include <queue>
#include <fstream>
#define WM_USER_THREAD	WM_USER+214

using namespace std;
using namespace boost;
class CSendEnvironment : public IEnvironment,public IOperatorArray,public IOutputInfo,public IPDU_Pipe,public IPDUServer
{
protected:
	std::string	m_strAppPath;	
	std::string m_strCfgFile;
	LONG	m_sst;
public:
	CSendEnvironment(std::string strAppPath,HWND hFrame){
		filesystem::directory_iterator end;
		for(filesystem::directory_iterator iter(strAppPath);iter != end;++iter){
			if(!filesystem::is_directory(iter->filename())){
				string strDllName = iter->filename();
				if(algorithm::iends_with(strDllName,".dll")){
					LoadLib(strAppPath,strDllName);
				}
			}
		}
		m_hFrame = hFrame;
		m_strAppPath = strAppPath;
		m_strCfgFile = m_strAppPath + "\\BRIV_Env.rpc";
		m_sst = SS_STOP;
	};
	virtual ~CSendEnvironment(){};

public:
	BOOL Start(){
		boost::property_tree::ptree pt;
		boost::property_tree::ini_parser::read_ini(m_strCfgFile,pt);
		BOOST_FOREACH(ITransport* pT,m_OperatorArr)
		{
			DYWS::Self()->AddPipe(pT->get_Pipe());
			NYWS::Self()->AddPipe(pT->get_Pipe());
		}
		DYWS::Initialize(boost::lexical_cast<long>(pt.get<string>("PLSend.DYSoapPort","8096")),this);
		NYWS::Initialize(boost::lexical_cast<long>(pt.get<string>("PLSend.NYSoapPort","7653")),this);
		return TRUE;
	}
	VOID Stop(){
		DYWS::Self()->Stop();
		NYWS::Self()->Stop();
	}
public:
	std::string& get_ConfigFile(){
		return m_strCfgFile;
	};
	IOperatorArray* get_Operators(){	return (IOperatorArray*)this;	};
	IOutputInfo * get_OutputInfo(){	return (IOutputInfo*)this;	};
	IPDU_Pipe * get_PDUPipe(){	return (IPDU_Pipe*)this;	};
	IPDUServer * get_PDUServer(){return (IPDUServer*)this;	};
	VOID NotifyStatus(long sst){	::PostMessage(m_hFrame,WM_USER_THREAD,1,sst);	};
protected:
	void LoadLib(string strAppPath,string strLibFile){
		wstring wstrFile = FrameFunc::s2ws(strAppPath +"\\" + strLibFile);
		HMODULE hModule = LoadLibrary(wstrFile.c_str());
		SD_OPERATOR_GEN_PROC lpProc = (SD_OPERATOR_GEN_PROC)GetProcAddress(hModule, "sdOperatorGEN");
		if(lpProc == NULL){
			FreeLibrary(hModule);
			return;
		}
		m_LibHandleArr.push_back(hModule);
		m_LibNameArr.push_back("<" + strLibFile + ">");
		m_OperatorArr.push_back(lpProc());
	};
private:
	vector<ITransport*>	m_OperatorArr;
	vector<string>		m_LibNameArr;
	vector<HMODULE>		m_LibHandleArr;
private:
	BOOL Capacity(long nSize){
//		for_each(m_OperatorArr.begin(),m_OperatorArr.end(),boost::bind(&IPDU_Pipe::Capacity,boost::bind(&ITransport::get_Pipe,_1),nSize))
		for(long i = 0;i < m_OperatorArr.size();++i)
			m_OperatorArr[i]->get_Pipe()->Capacity(nSize);
		return TRUE;
	};
	VOID Push(const PDU_HEADER* pPDU,long nSize){
		for(long i = 0;i < m_OperatorArr.size();++i)
			m_OperatorArr[i]->get_Pipe()->Push(pPDU,nSize);
	};
public:	//OperaotrArray
	long get_Count(){	return m_OperatorArr.size();	};
	ITransport * get_Operator(long i){	return (i >= m_OperatorArr.size() || i < 0) ? NULL : m_OperatorArr[i];};
	std::string get_OperatorDescribe(long i){	
		string strRet;
		ITransport* pOper = get_Operator(i);
		if(pOper) strRet = pOper->get_Describe();
		return strRet;
	};
	std::string get_OperatorSource(long i){return m_LibNameArr[i];};
private:
	HWND			m_hFrame;
	boost::mutex	m_sign;
	queue<string>		m_strInfoQueue;
public: //OutputInfo
	VOID Output(const string& strInfo){
		boost::mutex::scoped_lock lock(m_sign);
		m_strInfoQueue.push(strInfo);
		::PostMessage(m_hFrame,WM_USER_THREAD,0,0);
	};
	VOID OutputLineEnd(const string& strInfo){
		boost::mutex::scoped_lock lock(m_sign);
		m_strInfoQueue.push(strInfo);
		::PostMessage(m_hFrame,WM_USER_THREAD,0,1);
	};
	VOID StaticOutput(const string& strInfo){
		boost::mutex::scoped_lock lock(m_sign);
		m_strInfoQueue.push(strInfo);
		::PostMessage(m_hFrame,WM_USER_THREAD,0,2);
	};
	VOID AddTime2LineEnd(){
		boost::mutex::scoped_lock lock(m_sign);
		boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
		m_strInfoQueue.push(boost::posix_time::to_simple_string(now));
		::PostMessage(m_hFrame,WM_USER_THREAD,0,1);
	};
	std::string get_Info(){
		boost::mutex::scoped_lock lock(m_sign);
		std::string ret;
		if(!m_strInfoQueue.empty()){
			ret = m_strInfoQueue.front();
			m_strInfoQueue.pop();
		}
		return ret;
	};
	VOID Log(const std::string & strInfo){
		std::string strLogFile = m_strAppPath + "\\birtv.log";
		std::ofstream fout(strLogFile.c_str(),std::ios::app);
		boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
		fout << "-------" << now << "-------" << endl;
		fout << strInfo << endl;
		fout.close();
	};

};
